﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using __Able.Network.Utils;

namespace __Able.Network.Packets
{
    /// <summary>
    /// 基本协议族的输入包基类:
    ///  1. 包头标志，1字节，0x02
    ///  2. 服务器端版本代码, 2字节
    ///  3. 命令，2字节
    ///  4. 包序号，2字节
    ///  5. 包体
    ///  6. 包尾标志，1字节，0x03   
    /// 	在LumaQQ中，这边还定义了元数据。
    /// </summary>
    public abstract class _BasicInPacket : _InPacket
    {
        /// <summary>
        /// 服务器端版本号 (不一定) 不一定真的是表示服务器端版本号，似乎和发出的包不同，这个有其他的含义， 感觉像是包的类型标志
        /// </summary>
        public const ushort SERVER_VERSION_0100 = 0x0100;
        /// <summary>
        /// 基本协议族输入包的包头长度
        /// </summary>
        public const int LENGTH_BASIC_FAMILY_IN_HEADER = 7;
        /// <summary>
        /// 基本协议族包尾长度
        /// </summary>
        public const int LENGTH_BASIC_FAMILY_TAIL = 1;
        /// <summary>
        /// 基本协议族输入包的包头长度
        /// </summary>
        public const int A_LENGTH_BASIC_FAMILY_IN_HEADER = 7;
        /// <summary>
        /// 基本协议族包尾长度
        /// </summary>
        public const int B_LENGTH_BASIC_FAMILY_TAIL = 1;

        /// <summary>
        /// </summary>
        /// <param name="command">The command.</param>
        /// <param name="user">The user.</param>
        public _BasicInPacket(ushort command, User user)
            : base((byte)_HeaderFamily.HEADER_BASIC_FAMILY, SERVER_VERSION_0100, command, user) { }
        /// <summary>
        /// 构造一个指定参数的包.从buf的当前位置开始解析直到limit
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="user">The user.</param>
        public _BasicInPacket(ByteBuffer buf, User user) : base(buf, user) { }
        /// <summary>
        /// 构造一个InPacket，从buf的当前位置解析length个字节
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="length">The length.</param>
        /// <param name="user">The user.</param>
        public _BasicInPacket(ByteBuffer buf, int length, User user) : base(buf, length, user) { }
        /// <summary>
        /// 从buf的当前位置解析包头
        /// </summary>
        /// <param name="buf">The buf.</param>
        protected override void ParseHeader(ByteBuffer buf)
        {
            if (!user.IsUdp)
                buf.GetChar();
            Header = buf.Get();
            Source = buf.GetChar();
            Command = buf.GetUShort();
            Sequence = buf.GetChar();
        }

        protected override void PutHead(ByteBuffer buf)
        {
            if (!user.IsUdp)
                buf.PutUShort(0);
            buf.Put((byte)Header);
            buf.PutUShort(Source);
            buf.PutUShort((ushort)Command);
            buf.PutUShort(Sequence);
        }

        /// <summary>
        /// 从buf的当前未知解析包尾
        /// </summary>
        /// <param name="buf">The buf.</param>
        protected override void ParseTail(ByteBuffer buf)
        {
            buf.Get();
        }
        /// <summary>
        /// 初始化包体
        /// </summary>
        /// <param name="buf">The buf.</param>
        protected override void PutBody(ByteBuffer buf)
        {

        }
        /// <summary>
        /// 将包尾部转化为字节流, 写入指定的ByteBuffer对象.
        /// </summary>
        /// <param name="buf">The buf.</param>
        protected override void PutTail(ByteBuffer buf)
        {
            buf.Put((byte)_TailFamily.TAIL_BASIC_FAMILY);
        }
        /// <summary>
        /// 包的描述性名称
        /// </summary>
        /// <returns></returns>
        public override string PacketName
        {
            get
            {
                return "Unknown Incoming Packet - 0x" + Command.ToString("X");
            }
        }

        /// <summary>
        /// 得到包体的字节数组
        /// </summary>
        /// <param name="buf">The buf.</param>
        /// <param name="length">包总长度</param>
        /// <returns>包体字节数组</returns>
        protected override byte[] GetBodyBytes(ByteBuffer buf, int length)
        {
            // 得到包体长度
            int bodyLen = length - LENGTH_BASIC_FAMILY_IN_HEADER - LENGTH_BASIC_FAMILY_TAIL;
            if (!user.IsUdp) bodyLen -= 2;
            // 得到加密的包体内容
            byte[] body = buf.GetByteArray(bodyLen);
            return body;
        }
        /// <summary>
        /// 得到UDP形式包的总长度，不考虑TCP形式
        /// </summary>
        /// <param name="bodyLength">包体长度.</param>
        /// <returns>包长度</returns>
        protected override int GetLength(int bodyLength)
        {
            return A_LENGTH_BASIC_FAMILY_IN_HEADER + B_LENGTH_BASIC_FAMILY_TAIL + bodyLength + (user.IsUdp ? 0 : 2);
        }
        /// <summary>
        /// 包头长度
        /// </summary>
        /// <returns>包头长度</returns>
        protected override int GetHeaderLength()
        {
            return A_LENGTH_BASIC_FAMILY_IN_HEADER + (user.IsUdp ? 0 : 2);
        }
        /// <summary>
        /// 包尾长度
        /// </summary>
        /// <returns>包尾长度</returns>
        protected override int GetTailLength()
        {
            return B_LENGTH_BASIC_FAMILY_TAIL;
        }

        /// <summary>
        /// 标识这个包属于哪个协议族
        /// </summary>
        /// <returns></returns>
        public override uint GetFamily()
        {
            return (uint)_ProtocolFamily.PROTOCOL_FAMILY_BASIC;
        }
        public override byte[] GetDecryptKey(byte[] body)
        {
            return user.SessionKey;
        }
        public override byte[] GetEncryptKey(byte[] body)
        {
            return user.SessionKey;
        }
        public override byte[] GetFallbackDecryptKey(byte[] body)
        {
            return user.PasswordKey;
        }
    }
}
